package educrypt.ciphers.playfair;

import java.util.ArrayList;
import java.util.List;

import educrypt.commons.Alphabet;

class PlayfairBigrams {

	private List<String> data;

	public PlayfairBigrams(String data, Alphabet alphabet, char separatorSymbol) {
		this.data = generateBigrams(data, alphabet, separatorSymbol);
	}

	private List<String> generateBigrams(String data, Alphabet alphabet,
			char separatorSymbol) {
		List<String> ngrams = new ArrayList<String>();
		StringBuffer ngram = new StringBuffer();

		char firstValidSymbol = 0;
		for (int index = 0; index < data.length(); index++) {
			char symbol = data.charAt(index);
			boolean validSymbol = alphabet.containsSymbol(symbol);
			if (firstValidSymbol == 0) { // First symbol to add
				ngram.append(symbol);
				if (validSymbol) {
					firstValidSymbol = symbol;
				}
			} else if (firstValidSymbol != 0) { // Second symbol to add
				boolean repeatedSymbol = firstValidSymbol == symbol;
				if (validSymbol && repeatedSymbol) {
					ngram.append(separatorSymbol);
					ngrams.add(ngram.toString());
					// initialize next bigram
					firstValidSymbol = symbol;
					ngram = new StringBuffer().append(symbol);
				} else if (validSymbol && !repeatedSymbol) {
					ngram.append(symbol);
					ngrams.add(ngram.toString());
					// initialize next bigram
					firstValidSymbol = 0;
					ngram = new StringBuffer();
				} else { // non valid symbol
					ngram.append(symbol);
				}
			}
			boolean lastSymbolProcessed = index == data.length() - 1;
			if (lastSymbolProcessed) {
				if (firstValidSymbol == 0 && ngram.length() > 0) {
					// Adding two separator symbol to complete the bigram in
					// order to not to lose the unknown symbols that it contains
					ngram.append(separatorSymbol).append(separatorSymbol);
					ngrams.add(ngram.toString());
				} else if (firstValidSymbol != 0) {
					// Adding one separator symbol to complete the bigram
					ngram.append(separatorSymbol);
					ngrams.add(ngram.toString());
				}
			}
		}
		return ngrams;
	}

	public String getBigram(int index) {
		return this.data.get(index);
	}

	public int size() {
		return data.size();
	}

	public String toString() {
		return data.toString();
	}
}
